/*
 *  meshmanager.h
 *  gmit
 *
 *  Class MeshManager
 *
 *  Description:
 *    MeshManager provides memory storage of mesh components,  and several query
 *    operations on mesh. The information of mesh's GEOMETRIC part  is read from
 *    external mesh file in some format. That is the  coordinates  of grids, and
 *    the connectivity among them.  The  PHYSICAL  part of  mesh is set by upper 
 *    level application.
 *    
 *  Details:
 *    
 *
 *  Created by DONG Li on 4/11/10.
 *  Copyright 2010 LASG/IAP. All rights reserved.
 *
 */

#ifndef MESHMANAGER_H
#define MESHMANAGER_H

#include <string>

#include "mesh.h"

typedef enum { // The mesh type is categorized according to Arakawa definition.
    MeshA,
    MeshC
} MeshType;

typedef enum {
    Structured,
    Unstructured
} MeshStructure;

typedef enum {
    Uniform,
    Nonuniform
} MeshForm;

typedef enum {
    Triangular,
    Quadrilateral
} CellType;

typedef enum {
    Periodic
} BoundaryType;

// ***************************************************************** MeshManager

template <typename VT, typename ET, typename CT>
class MeshManager
{
public:
    MeshManager();
    ~MeshManager();
    // mesh file IO
    void readMeshFile(const string& meshFileName);
    void writeMeshFile() const;
#ifdef MESHCREATOR 
    // mesh construction methods
    //   set mesh parameters
    void setMeshType(const MeshType t) { this->meshType = t; }
    void setMeshStructure(const MeshStructure s) { this->meshStructure = s; }
    void setMeshForm(const MeshForm f) { this->meshForm = f; }
    void setNumDim(const int nd);
    //   for structured and uniform mesh only
    void setNumCell(const int dimId, const int nx);
    void setBndX(const int dimId, const double x1, const double x2);
    void setBndType(const int dimId, const int sideId, const BoundaryType);
    double getDx(const int dimId) const;
    //   create cell in different types
    void createVertexGridCell(const CellType, const vector<Grid<VT> >&, int*);
    void createEdgeCntrGridCell(const CellType, const vector<Grid<ET> >&, int*);
    void createCellCntrGridCell(const CellType, const vector<Grid<CT> >&, int*);
#endif
    // mesh interface for external computational components
    int getNumCell(const int dimId) const;
    int queryLocation(const vector<double>& x) const;
    void checkBoundary(vector<double>& x) const;
    
protected:
    // mesh parameters
    MeshType meshType;
    MeshStructure meshStructure;
    MeshForm meshForm;
    int numDim;
    // mesh components
    // a. vertex grids
    vector<Grid<VT> > vertexGrid;
    vector<Edge> vertexGridMeshEdges;
    vector<Cell> vertexGridMesh;
    // b. edge-centered grids
    vector<Grid<ET> > edgeCntrGrid;
    vector<Edge> edgeCntrGridMeshEdges;
    vector<Cell> edgeCntrGridMesh;
    vector<Grid<ET> > edgeCntrGridEW;
    vector<Edge> edgeCntrGridEWMeshEdges;
    vector<Cell> edgeCntrGridEWMesh;
    vector<Grid<ET> > edgeCntrGridNS;
    vector<Edge> edgeCntrGridNSMeshEdges;
    vector<Cell> edgeCntrGridNSMesh;
    // c. cell-centered grids
    vector<Grid<CT> > cellCntrGrid;
    vector<Edge> cellCntrGridMeshEdges;
    vector<Cell> cellCntrGridMesh;
    // spatial parameters, ONLY active when mesh is structured and uniform
    int numCell[3];
    double span[3], dx[3];
    double bndX[3][2];
    BoundaryType bndType[3][2];
};

#include "meshmanager.cpp"

#endif